/*
 * Copyright (c) 2011. c.mueller
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * The Software shall be used for Good, not Evil.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package de.altitude.cimuelle.commandhandles;

import de.altitude.cimuelle.Config;
import de.altitude.cimuelle.coop.CoopDataHandler;
import de.altitude.cimuelle.db.DatabaseGoals;
import de.altitude.cimuelle.db.DatabaseKillers;
import de.altitude.cimuelle.db.DatabaseManager;
import de.altitude.cimuelle.enums.Perk;
import de.altitude.cimuelle.enums.Plane;
import de.altitude.cimuelle.enums.Skin;
import de.altitude.cimuelle.utils.ServerUtils;
import de.altitudecustomcommands.Player;
import de.altitudecustomcommands.playerHandler;
import de.altitudecustomcommands.serverInformations;
import org.apache.log4j.Logger;

import java.util.Arrays;
import java.util.Map;

/**
 * Class description:
 * processes clientoperations (remove, kill, goal, assist)
 * User: cybernaut
 * Date: 07.10.11
 * Time: 22:18
 */
public class TypeClientOperations {
    private final playerHandler playerList;
    @SuppressWarnings({"FieldCanBeLocal"})
    private final serverInformations server;

    private static final Logger LOGGER = Logger.getLogger("TypeClientOperations");

    public TypeClientOperations(playerHandler playerList, serverInformations server) {
        this.playerList = playerList;
        this.server = server;
    }

    public void typeClientNicknameChange(Map json) {
        (this.playerList.getPlayerByVaporID((String) json.get("vaporId")))
                .setName((String) json.get("newNickname"));
    }

    public void typeClientRemove(Map json) {
        this.playerList.removePlayerByVaporID((String) json.get("vaporId"));
    }

    public void typeClientKill(Map json, String port, int playerId) {
        int victim = ((Number) json.get("victim")).intValue();
        int player = ((Number) json.get("player")).intValue();
        String source = String.valueOf(json.get("source"));

        Player victimP = null;
        if (victim > -1) {
            victimP = playerList.getFirstPlayerByPortAndId(port, victim);
            updatePlayerIsAlive(victimP, false);
            CoopDataHandler.updateGameStatsKill(port, victimP);
        }
        if ("plane".equals(source) && player > -1 && victim > -1) {
            // killed by another player
            killUpdateStats(port, (Number) json.get("time"), playerId, victim, ((Number) json.get("xp")).intValue(), false);
        } else if ("plane".equals(source) && player == -1 && victimP != null) {
            // killed by crash
            LOGGER.info(port + ":Player " + victimP.getName() + " crashed.");
        } else if ("turret".equals(source) && player == -1 && victimP != null) {
            // killed by turret
            LOGGER.info(port + ":Player " + victimP.getName() + " got killed by a turret.");
        }
    }

    private void killUpdateStats(String port, Number time, int playerId, Number victim, int xp, boolean assist) {
        for (Player player : playerList.getPlayersByPortAndId(port, playerId)) {
            player.getStats().increaseKilledPlanes();
            Player victimP = playerList.getFirstPlayerByPortAndId(port, victim.intValue());
            LOGGER.info(port + ":Killstats got kill from " + playerId + " (" + player.getName() + ") victim + " + victimP.getPlayerNumber() + " (" + victimP.getName() + ").");
            if (ServerUtils.checkCountingRequirements(port, playerList)) {
                if (assist) {
                    DatabaseManager.getInstance().addPointToPlayerForAssistedKills(player);
                } else {
                    DatabaseManager.getInstance().addPointToPlayerForKills(player);
                    DatabaseManager.getInstance().addPointToPlayerForDeaths(victimP);
                }
                new DatabaseKillers(port, time.longValue(), player, victimP, xp, assist);
            } else {
                LOGGER.info(new StringBuilder().append("Not enough players online to count killing. players online: ").append(Arrays.toString(playerList.getPlayersByPort(port))).append(" on port ").append(port).toString());
            }
        }
    }

    private void updatePlayerIsAlive(Player victim, boolean isAlive) {
        victim.setAlive(isAlive);
    }

    public void typeClientAssist(Map json, String port, int playerId) {
        Number victim;
        if (json.containsKey("victim")) {
            victim = (Number) (json.get("victim"));
        } else {
            victim = -1;
        }
        killUpdateStats(port, (Number) json.get("time"), playerId, victim, ((Number) json.get("xp")).intValue(), true);
    }

    public void typeGoal(Map json, String port, int playerId) {
        LOGGER.info(port + ":A goal has been achieved.");
        if (ServerUtils.checkCountingRequirements(port, playerList)) {
            Player player = playerList.getFirstPlayerByPortAndId(port, playerId);
            new DatabaseGoals(port, (Number) json.get("time"), player, false);
            DatabaseManager.getInstance().addPointToPlayerForGoals(player);
            Number assister = (Number) json.get("assister");
            if (assister.intValue() > -1) {
                Player assiterP = playerList.getFirstPlayerByPortAndId(port, assister.intValue());
                new DatabaseGoals(port, (Number) json.get("time"), assiterP, true);
                DatabaseManager.getInstance().addPointToPlayerForAssistedGoals(assiterP);
            }
        }

    }

    public void typeSpawn(String port, int playerId, Map json) {
        //    "plane":"Bomber","player":0,"perkRed":"Bombs","perkGreen":"Flexible Wings","team":3,"type":"spawn","perkBlue":"Turbocharger","skin":"No Skin"}
        String plane = String.valueOf(json.get("plane"));
        String perkRed = String.valueOf(json.get("perkRed"));
        String perkGreen = String.valueOf(json.get("perkGreen"));
        String perkBlue = String.valueOf(json.get("perkBlue"));
        int team = ((Number) json.get("team")).intValue();
        String skin = String.valueOf(json.get("skin"));

        Player player = playerList.getFirstPlayerByPortAndId(port, playerId);
        player.setSpawnData(
                Plane.getPlane(plane),
                Perk.getPerk(perkRed),
                Perk.getPerk(perkGreen),
                Perk.getPerk(perkBlue),
                Skin.getSkin(skin),
                team);

        if (Config.getInstance().isCoopRankingActiveByPort(port)) {
            CoopDataHandler.addPlayerToTeam(port, player);
        }
    }
}
